package demo.controller;

import cn.hutool.core.bean.BeanUtil;
import demo.Result;
import demo.dto.*;
import demo.entity.*;
import demo.service.*;
import demo.util.DateUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 评价 Controller
 *
 * @author 肖溥博文
 * @version 1.3
 */
@RestController
public class CommentController {
    @Autowired
    CommentService commentService;
    @Autowired
    UserService userService;
    @Autowired
    ScoreService scoreService;
    @Autowired
    UserCompanyService userCompanyService;
    @Autowired
    DepartmentService departmentService;
    @Autowired
    CompanyService companyService;

    /**
     * 按 工作经历 获取所有评价
     *
     * @param userCompany 一个 userCompany 对象，其中必须包含一个 id
     * @return Result json
     */
    @PostMapping("/listComments")
    @RequiresAuthentication
    public Result listComments(@RequestBody UserCompany userCompany) {
        List<Comment> comments = commentService.listComments(userCompany);
        List<ResponseUserCommentDto> responseUserCommentDtos = new ArrayList<>();

        for (Comment comment : comments) {
            ResponseUserCommentDto responseUserCommentDto = new ResponseUserCommentDto();
            BeanUtil.copyProperties(comment, responseUserCommentDto);
            responseUserCommentDto.setDate(DateUtil.format(comment.getDate()));
            responseUserCommentDto.setUserNameCommenter(userService.findUserByUid(comment.getUidCommenter()).getUserName());
            responseUserCommentDto.setUserNameEmployee(userService.findUserByUid(comment.getUidEmployee()).getUserName());
            responseUserCommentDto.setScores(scoreService.listScores(comment.getCommentId()));
            responseUserCommentDto.setAverage((Double) scoreService.getScore(comment).getData());
            responseUserCommentDtos.add(responseUserCommentDto);
        }

        return Result.success("评价查询成功", responseUserCommentDtos);
    }

    /**
     * 按传入的 json 数据添加评价
     *
     * @param requestAddCommentDto 传入的 json
     * @return Result 对象
     */
    @PostMapping("/addComment")
    @RequiresAuthentication
    @RequiresRoles("HR")
    public Result addComment(@RequestBody RequestAddCommentDto requestAddCommentDto) {
        Result result = commentService.add(requestAddCommentDto.getComment());
        scoreService.add(requestAddCommentDto.getScores(), (Long) result.getData());
        return Result.success("评价成功");
    }

    /**
     * 按传入的评价 id 获取该评价的总评分
     *
     * @param comment 传入的 Comment json
     * @return 该结果对象，包含该评价的总评分
     */
    @PostMapping("/getScore")
    @RequiresAuthentication
    public Result getScore(@RequestBody Comment comment) {
        return scoreService.getScore(comment);
    }

    /**
     * 按 工作经历 获取平均分
     *
     * @param userCompany 工作经历号
     * @return 结果对象，包含该工作经历的平均分
     */
    @PostMapping("/getAverageScoreOfUserCompany")
    @RequiresAuthentication
    public Result getAverageScoreOfUserCompany(@RequestBody UserCompany userCompany) {
        Result isUserCompanyExistResult = userCompanyService.isUserCompanyExist(userCompany);
        if (isUserCompanyExistResult.getCode() != 200) {
            return isUserCompanyExistResult;
        }

        return commentService.getAverageScoreOfUserCompany(userCompany);
    }

    /**
     * 按 部门 获取部门当前所有员工的平均分
     *
     * @param department 工作经历号
     * @return 结果对象，包含该工作经历的平均分
     */
    @PostMapping("/getAverageScoreOfDepartment")
    public Result getAverageScoreOfDepartment(@RequestBody Department department) {
        Department departmentFound = departmentService.findByDepartmentId(department.getDepartmentId());
        if (departmentFound == null) {
            return Result.error("不存在该部门");
        }

        List<UserCompany> userCompanies =
            userCompanyService.findLatestUserCompanyByDepartmentId(department.getDepartmentId());

        double total = 0.0;
        int count = 0;
        for (UserCompany userCompany : userCompanies) {
            List<Comment> comments = commentService.listComments(userCompany);
            Result eachUserCompanyResult = getAverageScoreOfUserCompany(userCompany);
            if (eachUserCompanyResult.getData() != null) {
                count++;
                double score = (double) eachUserCompanyResult.getData();
                if (score < 0) {
                    score = 0.0;
                }
                total += (score);
            }
        }

        if (count == 0) {
            return Result.success("该部门没有任何人在当前职位得到评分");
        }

        total = total / count;
        return Result.success("部门评价得分查询成功", total);
    }


    /**
     * 按 用户 id 获取历次平均得分
     *
     * @param requestWithLongDto 必须包含一个 用户 id
     * @return 结果对象，包含折线图数据
     */
    @PostMapping("/getScoresOfUser")
    public Result getScoresOfUser(@Validated @RequestBody RequestWithLongDto requestWithLongDto) {
        Long uid = requestWithLongDto.getId();
        List<UserCompany> userCompanies = userCompanyService.findUserCompaniesByUid(uid);
        if (userCompanies == null || userCompanies.isEmpty()) {
            return Result.success("该用户暂无工作经历");
        }

        List<Double> averages = new ArrayList<>();
        List<String> details = new ArrayList<>();
        for (UserCompany userCompany : userCompanies) {
            List<Comment> comments = commentService.listComments(userCompany);
            int userCompanyCommentsCount = 0;
            for (Comment comment : comments) {
                Result scoreResult = scoreService.getScore(comment);
                if (scoreResult.getData() != null) {
                    Double averageScore = (Double) scoreResult.getData();
                    averages.add(averageScore);
                    userCompanyCommentsCount ++;
                }
            }
            System.out.println(userCompany);
            if (userCompanyCommentsCount > 0) {
                Company company = (Company) companyService.find(userCompany.getCompanyId()).getData();
                Department department = departmentService.findByDepartmentId(userCompany.getDepartmentId());
                String userCompanyString = company.getCompanyName() + " "
                    + department.getDepartmentName() + " "
                    + userCompany.getPosition();
                for (int i = 0; i < userCompanyCommentsCount; i++) {
                    details.add(userCompanyString);
                }
            }
        }
        ResponseWithChartDataDto responseWithChartDataDto = new ResponseWithChartDataDto();
        responseWithChartDataDto.setData(averages);
        responseWithChartDataDto.setDetails(details);
        return Result.success("用户历次工作记录的分数查找成功", responseWithChartDataDto);
    }

    /**
     * 按 uid 查询部门分数水平
     *
     * @param requestWithLongDto 必须包含用户 id
     * @return 不存在评价返回 -1
     * <br /> 部门只有该员工，返回 100%
     */
    @PostMapping("/getScoreLevelWithinDepartment")
    public Result getScoreLevelWithinDepartment(@Validated @RequestBody RequestWithLongDto requestWithLongDto) {
        Long uid = requestWithLongDto.getId();
        User user = userService.findUserByUid(uid);
        if (user == null) {
            return Result.error("用户不存在，分数查询失败");
        }

        Result findUserCompanyResult = userCompanyService.findLatestUserCompanyByUid(uid);
        if (findUserCompanyResult.getCode() != 200) {
            return Result.error("用户不在职，分数查询失败");
        }

        // 当用户当前工作经历没有评价时，返回 -1
        UserCompany userCompany = (UserCompany) findUserCompanyResult.getData();
        if (!commentService.existsComments(userCompany)) {
            return Result.success("用户不存在评价", -1);
        }

        Long departmentId = userCompany.getDepartmentId();
        Double myScore = (Double) commentService.getAverageScoreOfUserCompany(userCompany).getData();
        List<UserCompany> deparementUserCompanies =
            userCompanyService.findLatestUserCompanyByDepartmentId(departmentId);

        int lowerCount = 0;                             // 低于其分数的人
        int count = deparementUserCompanies.size();     // 总人数

        // 总人数小于 1 则抛异常
        if (count < 1) {
            throw new RuntimeException("异常：统计人数不合法");
        }

        // 总人数等于 1 返回 100%
        if (count == 1) {
            return Result.success("查询成功", 1);
        }

        for (UserCompany item : deparementUserCompanies) {
            Result getAverageScoreOfUserCompanyResult = commentService.getAverageScoreOfUserCompany(item);
            Double score = (Double) getAverageScoreOfUserCompanyResult.getData();
            if (score < myScore) {
                lowerCount++;
            }
        }

        return Result.success("查询成功", ((double) lowerCount) / count);
    }

    @PostMapping("/getScoreLevelWithinCompany")
    public Result getScoreLevelWithinCompany(@Validated @RequestBody RequestWithLongDto requestWithLongDto) {
        Long uid = requestWithLongDto.getId();
        User user = userService.findUserByUid(uid);
        if (user == null) {
            return Result.error("用户不存在，分数查询失败");
        }

        Result findUserCompanyResult = userCompanyService.findLatestUserCompanyByUid(uid);
        if (findUserCompanyResult.getCode() != 200) {
            return Result.error("用户不在职，分数查询失败");
        }

        // 当用户当前工作经历没有评价时，返回 -1
        UserCompany userCompany = (UserCompany) findUserCompanyResult.getData();
        if (!commentService.existsComments(userCompany)) {
            return Result.success("用户不存在评价", -1);
        }

        Long companyId = userCompany.getCompanyId();
        Double myScore = (Double) commentService.getAverageScoreOfUserCompany(userCompany).getData();
        List<UserCompany> companyUserCompanies =
            userCompanyService.listUserCompanies(companyId);

        int lowerCount = 0;                          // 低于其分数的人
        int count = companyUserCompanies.size();     // 总人数

        // 总人数小于 1 则抛异常
        if (count < 1) {
            throw new RuntimeException("异常：统计人数不合法");
        }

        // 总人数等于 1 返回 100%
        if (count == 1) {
            return Result.success("查询成功", 1);
        }

        for (UserCompany item : companyUserCompanies) {
            Result getAverageScoreOfUserCompanyResult = commentService.getAverageScoreOfUserCompany(item);
            Double score = (Double) getAverageScoreOfUserCompanyResult.getData();
            if (score < myScore) {
                lowerCount++;
            }
        }

        return Result.success("查询成功", ((double) lowerCount) / count);
    }
}
